Release 10.1A: OpenEdge Data Management:
SQL Development
Using the OpenEdge SQL Java classes
This section describes how you use the OpenEdge SQL Java classes to issue and process SQL statements in Java stored procedures.
To process SQL statements in a stored procedure, you must know whether the SQL statement generates output (in other words, if the statement is a query) or not.
SELECTstatements, for example, generate results: they retrieve data from one or more database tables and return the results as rows in a table.Whether a statement generates such an SQL result set determines which OpenEdge SQL Java classes you should use to issue it:
- To issue SQL statements that do not generate results (such as
INSERT,GRANT, orCREATE), use theSQLIStatementclass for one-time execution, or theSQLPStatementclass for repeated execution.- To issue SQL statements that generate results (
SELECTand, in some cases,CALL), use theSQLCursorclass to retrieve rows from a database or another procedure’s result set.In either case, if you want to return a result set to the application, use the
DhSQLResultSetclass to store rows of data in a procedure result set. You must useDhSQLResultSetmethods to transfer data from an SQL result set to the procedure result set for the calling application to process it. You can also useDhSQLResultSetmethods to store rows of data generated internally by the procedure.In addition, OpenEdge SQL provides the
DhSQLExceptionclass so procedures can process and generate Java exceptions through the try, catch, and throw constructs.Passing values to SQL statements
Stored procedures must be able to pass and receive values from SQL statements they execute. They do this through the
setParamandgetValuemethods.setParam method: pass input values to SQL statements
The
setParammethod sets the value of an SQL statement’s parameter marker to the specified value (a literal value, a procedure variable, or a procedure input parameter).The
setParammethod takes two arguments. This is the syntax forsetParam:
marker_numSpecifies the ordinal number of the parameter marker in the SQL statement that is to receive the value as an integer.
1denotes the first parameter marker,2denotes the second, n denotes the nth.
valueSpecifies a literal, variable name, or input parameter that contains the value to be assigned to the parameter marker.
Example 9–9 shows a segment of a stored procedure that uses
setParamto assign values from two procedure variables to the parameter markers in an SQLINSERTstatement. When the procedure executes, it substitutes the value of thecust_numberprocedure variable for the first parameter marker and the value of thecust_namevariable for the second parameter marker.
getValue method: pass values from SQL result sets to variables
The
getValuemethod of theSQLCursorclass assigns a single value from an SQL result set (returned by an SQL query or another stored procedure) to a procedure variable or output parameter using the following syntax:
col_numSpecifies the desired column of the result set as integer.
getValueretrieves the value in the currently fetched record of the column denoted by col_num.1denotes the first column of the result set,2denotes the second, n denotes the nth.sql_data_typeSpecifies the corresponding SQL data type.
This example shows how the
getValue()method works. This method returns a Java object that must be cast to the corresponding SQL data type:
Passing values to and from stored procedures: input and output parameters
Applications need to pass and receive values from the stored procedures they call. They do this through input and output parameters. When applications process the
CREATE PROCEDUREstatement, the SQL engine declares Java variables of the same name. Therefore, the stored procedure can refer to input and output parameters as if they were Java variables declared in the body of the stored procedure.Procedure result sets are another way for applications to receive output values from a stored procedure. Procedure result sets provide output in a row-oriented tabular format.
Parameter declarations include the parameter type (
IN,OUT, orINOUT), the parameter name, and SQL data type.Declare input and output parameters in the specification section of a stored procedure, as shown in Example 9–10.
When the
order_entrystored procedures executes, the calling application passes values for thecust_name,item_num,quantity, andorder_numinput parameters. The body of the procedure refers to them as Java variables. Similarly, Java code in the body oforder_entryprocesses and returns values in thestatus_codeandorder_numoutput parameters.Implicit data type conversion between SQL and Java types
When the OpenEdge SQL Engine creates a stored procedure, it converts the type of any input and output parameters.
The java.lang package, part of the Java core classes, defines classes for all the primitive Java types that “wrap” values of the corresponding primitive type in an object. The OpenEdge SQL Engine converts the SQL data types declared for input and output parameters to one of these wrapper types, as shown in Table 9–2.
Be sure to use wrapper types when declaring procedure variables to use as arguments to the
getValue,setParam, andsetmethods. These methods take objects as arguments and will generate compilation errors if you pass a primitive type to them.The following example illustrates the use of the Java wrapper type Long for a SQL type
INTEGER:
When the OpenEdge SQL Engine submits the Java class it creates from the stored procedure to the Java compiler, the compiler checks for data-type consistency between the converted parameters and variables you declare in the body of the stored procedure.
To avoid type mismatch errors, use the data-type mappings shown in Table 9–2 for declaring parameters and result-set fields in the procedure specification and the Java variables in the procedure body.
Executing an SQL statement
If an SQL statement does not generate a result set, stored procedures can execute the statement in one of two ways:
Table 9–3 shows the SQL statements that do not generate result sets. You can execute these statements in a stored procedure using either the
SQLIStatementor theSQLPStatementclass.
Immediate execution
Use immediate execution when a procedure must execute an SQL statement only once.
This stored procedure in this sample script inserts a row in a table. The constructor for
SQLIStatementtakes the SQLINSERTstatement as its only argument. In Example 9–11, the statement includes five parameter markers.
Prepared execution
Use prepared execution when you must execute the same SQL statement repeatedly. Prepared execution avoids the overhead of creating multiple
SQLIStatementobjects for a single statement.There is an advantage to prepared execution when you execute the same SQL statement from within a loop. Instead of creating an object with each iteration of the loop, prepared execution creates an object once and supplies input parameters for each execution of the statement.
Once a stored procedure creates an
SQLPStatementobject, you can execute the object multiple times, supplying different values for each execution.Example 9–12 extends the previous example to use prepared execution.
Retrieving data: the SQLCursor class
Methods of the
SQLCursorclass let stored procedures retrieve rows of data. When stored procedures create an object from theSQLCursorclass, they pass as an argument an SQL statement that generates a result set. The SQL statement is either aSELECTor aCALLstatement:Either way, once the procedure creates an object from the
SQLCursorclass, the processing of result sets follows the same steps.
![]()
To process result sets:
- Open the cursor by using the
SQLCursor.openmethod.- Check whether there are any records in the result set by using the
SQLCursor.foundmethod.- If there are records in the result set, loop through the result set:
- Try to fetch a record by using the
SQLCursor.fetchmethod.- Check whether the fetch returned a record with the
SQLCursor.foundmethod.- If the fetch operation returned a record, assign values from the result-set record’s fields to procedure variables or procedure output parameters by using the
SQLCursor.getValuemethod.- Process the data.
- If the fetch operation did not return a record, exit the loop.
- Close the cursor by using the
SQLCursor.closemethod.Example 9–13 uses
SQLCursorto process the result set returned by anSQL SELECTstatement.
Stored procedures also use
SQLCursorobjects to process a result set returned by another stored procedure. Instead of aSELECTstatement, theSQLCursorconstructor includes aCALLstatement that invokes the desired procedure.Example 9–14 shows an excerpt from a stored procedure that processes the result set returned by another procedure,
get_customers.
Returning a procedure result set to applications: the RESULT clause and DhSQLResultSet
The
get_salprocedure in the previous example with aCREATE PROCEDUREuses theSQLCursor.getValuemethod to store the values of a database record in individual variables. The procedure did not, however, do anything with those values and they will be overwritten in the next iteration of the loop that fetches records.The
DhSQLResultSetclass provides a way for a procedure to store rows of data in a procedure result set so that the rows can be returned to the calling application. There can only be one procedure result set in a stored procedure.A stored procedure must explicitly process a result set to return it to the calling application:
When the SQL engine creates a Java class from a
CREATE PROCEDUREstatement that contains theRESULTclause, it implicitly instantiates an object of typeDhSQLResultSet, and calls itSQLResultSet. Invoke methods of theSQLResultSetinstance to populate fields and rows of the procedure result set.The next example extends the
get_salprocedure to return a procedure result set:
For each row of the SQL result set assigned to procedure variables, the procedure:
Handling null values
Stored procedures routinely must set and detect null values:
- Stored procedures might need to set the values of SQL statement input parameters or procedure result fields to null.
- Stored procedures must check if the value of a field in an SQL result set is null before assigning it through the
SQLCursor.getValuemethod. The OpenEdge SQL Engine generates a run-time error if the result-set field specified ingetValueisNULL.Setting SQL statement input parameters and procedure result set fields to null
Both the
setParammethod andsetmethod take objects as their value arguments. You can pass aNULLreference directly to the method or pass a variable that has been assigned the null value.Example 9–15 uses both techniques to set an SQL input parameter to
NULL.
Assigning null values from SQL result sets: the SQLCursor.wasNULL method
If the value of the field argument to the
SQLCursor.getValuemethod isNULL, the SQL engine returns a run-time error.Example 9–16 illustrates the error returned when the argument to
SQLCursor.getValueisNULL.
This means you must always check whether a value is null before attempting to assign a value in an SQL result set to a procedure variable or output parameter. The
SQLCursorclass provides thewasNULLmethod for this purpose.The
SQLCursor.wasNULLmethod returnsTRUEif a field in the result set is null. It takes a single integer argument that specifies which field of the current row of the result set to check.Example 9–17 illustrates using the
wasNULLmethod.
Handling errors
OpenEdge SQL stored procedures use standard Java try/catch constructs to process exceptions.
Any errors in SQL statement execution result in the creation of a
DhSQLExceptionclass object. When OpenEdge SQL detects an error in an SQL statement, it throws an exception. The stored procedure should use try/catch constructs to process such exceptions. ThegetDiagnosticsmethod of theDhSQLExceptionclass object provides a mechanism to retrieve different details of the error.The
getDiagnosticsmethod takes a single argument whose value specifies which error message detail it returns. See Table 9–4 for explanations of thegetDiagnosticserror-handling options.
Example 9–18 shows an excerpt from a stored procedure that uses
DhSQLException.getDiagnostics.
Stored procedures can also throw their own exceptions by instantiating a
DhSQLExceptionobject and throwing the object when the procedure detects an error in execution. The conditions under which the procedure throws the exception object are completely dependent on the procedure.Example 9–19 illustrates using the
DhSQLExceptionconstructor to create an exception object calledexcep. It then throws theexcepobject under all conditions.
Calling stored procedures from other stored procedures
Stored procedures and triggers can call other stored procedures. Nesting procedures lets you take advantage of existing procedures. Instead of rewriting the code, procedures can simply issue
CALLstatements to the existing procedures.Another use for nesting procedures is for assembling result sets generated by queries on different databases into a single result set. With this technique, the stored procedure processes multiple
SELECTstatements through multiple instances of theSQLCursorclass. For each of the instances, the procedure uses theDhSQLResultSetclass to add rows to the result set returned by the procedure.Stored procedure parameter requirements and usage
When one stored procedure is calling another stored procedure, the following requirements must be met for using the three parameter types in order to properly allocate the SQLDA structure to the correct size:
INOUT and OUT parameters when one Java stored procedure calls another
If an
OUTorINOUTparameter is of data typeCHARACTER, thengetParam()returns a Java String Object. You must declare a procedure variable of type String, and explicitly cast the value returned bygetParamto type String. Before callinggetParam()you must call theSQLCursor.wasNULLmethod to test whether the returned value is null. IfgetParam()is called for a null value, it raises aDhSQLException.The
getParam()method returns the value of anINOUTorOUTparameter identified by the number you specify in thefieldIndexparameter.getParam()returns the value as an object of the data type you specify in thefieldTypeparameter. SincegetParam()returns the result as an instance of classObject, you must explicitly cast yourinout_varvariable to the correct data type.These are the general steps to follow when calling one Java stored procedure from another:
Example 9–20 illustrates the steps required for calling one Java stored procedure from another.
|
Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095 |